<template>
    <div v-loading="loading" class="console-page forbid-select">
        <el-form inline :model="searchForm" class="e-page form-item" spellcheck="false" @submit.native.prevent>
            <el-row class="toolbar" ref="el">
                <el-col :span="3" style="padding-right: 5px">
                    <el-select v-model="searchForm.jobGroup" placeholder="执行器组" class="input-auto-resize" clearable>
                        <el-option v-for="item in groups" :key="item.value" :label="item.label" :value="item.value" />
                    </el-select>
                </el-col>
                <el-col :span="3" style="padding-right: 5px">
                    <el-select v-model="searchForm.triggerStatus" placeholder="执行方式" class="input-auto-resize"
                        clearable>
                        <el-option v-for="item in statusSelect" :key="item.value" :label="item.label"
                            :value="item.value" />
                    </el-select>
                </el-col>
                <el-col :span="3" style="padding-right: 5px">
                    <el-input class="input-auto-resize" v-model="searchForm.jobDesc" placeholder="任务描述" clearable />
                </el-col>
                <el-col :span="3" style="padding-right: 5px" v-permission="checkPermission">
                    <el-select v-model="searchForm.glueType" class="input-auto-resize" placeholder="任务类型" clearable>
                        <el-option v-for="item in jobType" :key="item" :label="item" :value="item"
                            v-permission="`/task/${item}`" />
                    </el-select>
                </el-col>
                <el-col :span="3" style="padding-right: 5px">
                    <el-select v-model="searchForm.author" placeholder="创建人" style="width: 100%;"
                        class="input-auto-resize" clearable>
                        <el-option v-for="item in usernames" :key="item.sequence" :label="item.username"
                            :value="item.username" />
                    </el-select>
                </el-col>
                <el-col :span="searchForm.glueType === 'bean' ? 3 : 6" style="padding-right: 5px">
                    <el-button type="primary" @click="searchTable" circle class="button-auto-resize"
                        native-type="submit" :icon="getIcon('search')" />
                </el-col>
                <el-col :span="3" style="text-align: right" v-permission="checkPermission">
                    <el-dropdown placement="bottom" trigger="click" @visible-change="handleVisible">
                        <span class="el-dropdown-link">
                            <el-button :icon="getIcon('plus')" circle class="button-auto-resize" />
                        </span>
                        <template #dropdown>
                            <el-dropdown-menu style="min-width: 150px;">
                                <span v-for="(task, index) in jobType" :key="index" v-permission="`/task/${task}`">
                                    <el-dropdown-item @click="add(task)" :icon="getIcon('ElementPlus')">
                                        <span>{{ task.toUpperCase() }}</span>
                                    </el-dropdown-item>
                                </span>
                            </el-dropdown-menu>
                        </template>
                    </el-dropdown>
                </el-col>
            </el-row>
        </el-form>
        <el-table :data="tableData" border header-cell-class-name="el-table-header-cell" cell-class-name="el-table-cell"
            class="e-page table-with-pagination" highlight-current-row>
            <el-table-column prop="id" label="任务ID" width="100" />
            <el-table-column prop="jobDesc" label="任务描述" min-width="250" />
            <el-table-column prop="jobGroup" label="执行器组" width="160">
                <template #default="scope">
                    <span>{{ getJobGroup(scope.row.jobGroup) }}</span>
                </template>
            </el-table-column>
            <el-table-column prop="glueType" label="任务类型" :width="fontAutoResize.size_9.value">
                <template #default="scope">
                    <el-tag type="primary" effect="plain" class="button-auto-resize" disable-transitions>{{
                        getGlueType(scope.row).toUpperCase() }}
                    </el-tag>
                </template>
            </el-table-column>
            <el-table-column prop="execType" label="NextRunTime" :width="fontAutoResize.size_12.value">
                <template #default="scope">
                    <span>{{ scope.row.triggerStatus === 1 ? timeFormatSeconds(scope.row.triggerNextTime) : "" }}</span>
                </template>
            </el-table-column>
            <el-table-column prop="jobStatus" label="任务最新状态" :width="fontAutoResize.size_8.value">
                <template #default="scope">
                    <el-tag :type="getTagType(scope.row)" effect="plain" class="button-auto-resize" disable-transitions>
                        {{ scope.row.lastHandlerStatus || '未执行' }}
                    </el-tag>
                </template>
            </el-table-column>
            <el-table-column prop="triggerStatus" label="执行方式" :width="fontAutoResize.size_8.value">
                <template #default="scope">
                    <el-tag :type="scope.row.triggerStatus === 1 ? 'success' : 'info'" effect="plain"
                        class="button-auto-resize" disable-transitions>
                        {{ scope.row.triggerStatus === 1 ? "自动执行" : "手动执行" }}
                    </el-tag>
                </template>
            </el-table-column>
            <el-table-column prop="author" label="创建人" min-width="200" />
            <el-table-column prop="addTime" label="创建时间" :width="fontAutoResize.size_11.value" />
            <el-table-column prop="updateTime" label="更新时间" :width="fontAutoResize.size_11.value" />
            <el-table-column fixed="right" label="操作" :width="operationWidth" className="operation-column">
                <template #default="scope">
                    <el-button circle class="button-auto-resize" @click="taskDetail(scope.row)"
                        :icon="getIcon('editPen')" type="primary" />
                    <el-button circle class="button-auto-resize" @click="changeTriggerStatus(scope.row)"
                        :icon="getIcon('SwitchButton')" type="primary" :confirm-title="getSwitchConfirmTitle(scope.row)"
                        v-permission="$permission.Update" />
                    <el-button type="danger" :icon="getIcon('delete')" circle class="button-auto-resize"
                        @click="deleteTask(scope.row)" :confirm-title="getDeleteConfirmTitle(scope.row)"
                        v-permission="$permission.Delete" />
                    <el-button :icon="getIcon('position')" circle class="button-auto-resize" @click="runTask(scope.row)"
                        v-permission="$permission.Execute" type="primary" />
                </template>
            </el-table-column>
        </el-table>
        <div style="height: 50px;">
            <el-pagination background @size-change="SizeChange" @current-change="CurrentChange"
                :current-page="currentPage" :page-sizes="page_sizes" :page-size="page_size"
                layout="total, sizes, prev, pager, next, jumper" prev-text="<上一页" next-text="下一页>" :total="total"
                class="e-page" />
        </div>
    </div>
</template>

<script setup>
import { timeFormatSeconds, getIcon } from "@/utils/tools"
import { useElMessage, useSetTableOperationWidth, useRequest } from "@usehook"
import { usePermission } from "@/directive/permission"
import router from "@/router"
import showRunOnce from "@/components/task"
import { fontAutoResize } from "@/utils/setting"
import { permission } from "@/utils/constant"
import storeInstance from "@/pinia"
import { addEmitterListener } from "@/utils/eventbus"

const { tagMenuStore } = storeInstance
const operationWidth = useSetTableOperationWidth(4)

let jobType = ["sql", "java", "etl", "batchEtl", "workflow"]

let tableData = $ref([])
let currentPage = $ref(1)
let page_size = $ref(0)
let total = $ref(0)
let statusSelect = $ref([{ value: 1, label: '自动执行' }, { value: 0, label: '手动执行' }])
let searchForm = $ref({
    jobDesc: '',
    jobGroup: null,
    executorHandler: '',
    triggerStatus: null,
    author: '',
    glueType: ""
})
let loading = $ref(false)
let page_sizes = [10, 30, 50, 100, 200]
let groups = $ref([])
let usernames = $ref([])
let agentList = $ref([])

const getJobGroup = (id) => {
    for (let group of groups) {
        if (group.value === id) {
            return group.label
        }
    }
    return id
}

const getTagType = (row) => {
    return row.lastHandlerStatus === '成功' ? 'success' : row.lastHandlerStatus === '失败' ? 'danger' : 'info'
}

let dbInfo = $ref(null)

const checkPermission = computed(() => {
    return usePermission(permission.Write) && jobType.map(e => usePermission(`/task/${e}`)).some(e => e)
})
const runTask = async (row) => {
    if (dbInfo === null) {
        const resData = await useRequest({ url: "/data/connection/getConnection" })
        if (resData && resData.status) {
            dbInfo = resData.data.db
        } else {
            useElMessage.error("数据库连接信息获取失败")
        }
    }

    const glueParams = JSON.parse(row.glueParams)
    const params = row.glueType === "GLUE_SQL" || row.glueType === "GLUE_GROOVY" ? glueParams.params : glueParams
    showRunOnce({ show: true, jobId: row.id, jobName: row.jobDesc, params, dbList: dbInfo, agentList })
}

const getSwitchConfirmTitle = (row) => {
    const id = row.id
    const status = row.triggerStatus
    const jobName = row.jobDesc
    const schedule = row.scheduleConf
    return `<strong style="font-size: calc(var(--font-size) - 2px);padding: 5px 0">${schedule ? status === 1 ? '确定关闭定时任务?' : '确定开启定时任务?' : '未配置Cron信息，无法开启定时任务'}</strong>
                                 <div style="display: flex;gap: 40px;color: teal;font-size: var(--font-size)">
                                     <div>任务ID：${id}</div>
                                     <div>任务名称：${jobName}</div>
                                     <div>任务类型：${getGlueType(row).toUpperCase()}</div>
                                 </div>`
}

const changeTriggerStatus = (row) => {
    const schedule = row.scheduleConf
    const id = row.id
    const status = row.triggerStatus

    if (!schedule) return
    loading = true
    useRequest({ url: status === 1 ? "/jobinfo/stop" : "/jobinfo/start", id: id, method: "post" }).then((resData) => {
        if (resData && resData.status) {
            useElMessage("定时任务" + (status === 1 ? "关闭" : "启动") + "成功")
        } else {
            useElMessage.error("定时任务" + (status === 1 ? "关闭" : "启动") + "失败")
        }
        refreshTable()
    }).finally(() => {
        loading = false
    })
}

const getGlueType = (row) => {
    if (row.glueType.startsWith("GLUE")) {
        let type = row.glueType.split("_")[1]
        return type === "GROOVY" ? "java" : type.toLowerCase()
    } else {
        return row.glueType.toLowerCase() + ":" + row.executorHandler
    }
}

const getTaskData = (params) => {
    loading = true
    useRequest(params).then((resData) => {
        if (resData && resData.status) {
            tableData = resData.data
            total = resData.totalRecord
        }
    }).finally(() => {
        loading = false
    })
}

const searchTable = () => {
    getTaskData({
        url: '/jobinfo/getPageData', ...searchForm, limit: page_size, page: 1
    })
    currentPage = 1
}

const refreshTable = () => {
    setTimeout(() => {
        getTaskData({
            url: '/jobinfo/getPageData', ...searchForm, limit: page_size, page: currentPage
        })
    }, 200)
}

const SizeChange = (val) => {
    getTaskData({
        url: '/jobinfo/getPageData', ...searchForm, limit: val, page: currentPage
    })
    page_size = val
}

const CurrentChange = (val) => {
    getTaskData({
        url: '/jobinfo/getPageData', ...searchForm, limit: page_size, page: val
    })
    currentPage = val
}

const getDeleteConfirmTitle = (row) => {
    const name = row.jobDesc
    const id = row.id
    return `<strong style="font-size: calc(var(--font-size) - 2px);padding: 5px 0;color: #ff6e6e">确认删除该任务?</strong>
                                 <div style="display: flex;gap: 40px;color: red;font-size: var(--font-size)">
                                     <div>任务ID：${id}</div>
                                     <div>任务名称：${name}</div>
                                     <div>任务类型：${getGlueType(row).toUpperCase()}</div>
                                 </div>`
}

const deleteTask = (row) => {
    const id = row.id
    for (let tagMenu of tagMenuStore.getTagMenu) {
        if (tagMenu.path === "/task/" + getGlueType(row) + "?id=" + id) {
            tagMenuStore.closeTagMenu(tagMenu)
        }
    }
    useRequest({ url: "/jobinfo/remove", id: id, method: "post" }).then((resData) => {
        if (resData && resData.status) {
            useElMessage("已删除")
            refreshTable()
        } else {
            if (resData.message) useElMessage.error(resData.message)
        }
    })
}

const taskDetail = (row) => {
    const title = row.jobDesc
    let index = '/task/' + getGlueType(row)
    tagMenuStore.setTitle(title)
    const query = { id: row.id }
    router.push({ path: index, query })
}

addEmitterListener("refreshTask", () => {
    searchTable()
})

const handleVisible = () => {
    document.querySelectorAll('[aria-hidden]').forEach(element => {
        element.removeAttribute('aria-hidden');
    })
}

const add = (task) => {
    tagMenuStore.setTitle("new")
    router.push('/task/' + task)
}

onMounted(() => {
    useRequest({
        'url': '/user/list/getData', 'search': JSON.stringify({ status: '1' }),
        'limit': 1000,
        'page': 1
    }).then(r => {
        if (r && r.data) {
            usernames = r.data
        }
    })

    useRequest('/jobgroup/getPageData').then(resp => {
        if (resp && resp.data) {
            for (let agent of resp.data) {
                groups.push({ label: agent.title, value: agent.id })
                for (const agentAddress of agent.registryList) {
                    agentList.push({ title: agent.title, appName: agent.appName, address: agentAddress })
                }
            }
        }
    })

    page_size = page_sizes[1]
    getTaskData({
        url: '/jobinfo/getPageData', ...searchForm, limit: page_size, page: currentPage
    })
})

</script>

<style scoped>
:deep(.iconfont) {
    width: 15px;
    /*font-size: 35px !important;*/
    line-height: 25px;
    margin-top: auto;
    margin-left: 5px;
    font-family: iconfont, serif !important;
}

:deep(.e-dropdown-menu, .el-dropdown-menu__item) {
    padding: 0 10px 0 0 !important;
}

:deep(.el-icon-point) {
    font-size: 13px !important;
}

:deep(.el-form-item) {
    margin-bottom: 0;
    width: 190px;
}

:deep(.el-form-item label) {
    line-height: 25px;
}

:deep(.el-form-item__content) {
    line-height: 25px;
    font-size: 12px;
    width: 110px;
}

:deep(.el-dropdown-menu__item) {
    padding: 8px 16px;
}
</style>

<style>
.dialog .el-dialog__header {
    padding-bottom: 0 !important;
}

.dialog.el-dialog {
    padding-bottom: 9px;
}

.dialog .el-dialog__footer {
    padding-top: 10px;
}
</style>